package com.itcs.box.server.resolver;

import com.alibaba.fastjson.JSON;
import com.itcs.ApplicationContextUtils;
import com.itcs.box.BoxConstants;
import com.itcs.box.domain.BoxRequest;
import com.itcs.box.domain.BoxResponse;
import com.itcs.box.server.callback.BoxCallBack;
import com.itcs.box.server.server.NettyChannelMap;
import com.itcs.box.server.service.SecurityService;
import com.itcs.box.util.LogUtils;
import com.itcs.eureka.service.PayApiFeignClientService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

/**
 * 功能描述:
 * <发送信息到支付平台线程>
 *
 * @ClassName: Send2AppThread
 * @Author: wanghui
 * @Date: 2019年05月17日 09:37:12
 *
 * @Copyright: 2019 Inc. All rights reserved. 注意: 本内容仅限于内部传阅,禁止外泄以及用于其他的商业目
 */
public class Send2AppThread extends Thread {
	private static Log logger = LogFactory.getLog(Send2AppThread.class);

	private ChannelHandlerContext channelHandlerContext;

	private BoxRequest boxRequest;

	private PayApiFeignClientService apiService;

	private String serverId;

	/**
	 * @Fields 回调
	 */
	private BoxCallBack boxCallBack;

	public Send2AppThread(PayApiFeignClientService apiService, String serverId,
						  ChannelHandlerContext channelHandlerContext, BoxRequest boxRequest) {
		this.apiService = apiService;
		this.serverId = serverId;
		this.channelHandlerContext = channelHandlerContext;
		this.boxRequest = boxRequest;

		InetSocketAddress socketAddress = (InetSocketAddress) channelHandlerContext.channel().remoteAddress();

		String channelId = "";
		String deviceId = boxRequest.getData().getDeviceId();
		if (deviceId != null) {
			channelId = NettyChannelMap.getChannelId(deviceId);
		}
		boxRequest.initChnanel(socketAddress.getHostString(), String.valueOf(socketAddress.getPort()), channelId);
	}

	public Send2AppThread(PayApiFeignClientService apiService, String serverId,
						  ChannelHandlerContext channelHandlerContext, BoxRequest boxRequest,
			BoxCallBack boxCallBack) {
		this(apiService, serverId, channelHandlerContext, boxRequest);
		this.boxCallBack = boxCallBack;
	}

	@Override
	public void run() {
		Map<String, Object> reqRecord = new HashMap<>();
		try {
			String messageType = boxRequest.getMessgeType();
			String tranId = "box_" + messageType;
			reqRecord.put(BoxConstants.BOX_REQ_KEY, boxRequest);
			logger.info("发送请求："+tranId);
			Map<String, Object> resMap = apiService.exchange(serverId,tranId,reqRecord);
			Object res = resMap.get(BoxConstants.BOX_RES_KEY);
			if (res != null) {
				BoxResponse boxResponse = (BoxResponse) resMap.get(BoxConstants.BOX_RES_KEY);
				if (boxResponse != null) {
					logger.info(LogUtils.build(boxResponse.getMessgeType(), "接收app返回通讯盒消息", "通讯盒:"
							+ boxResponse.getData().getDeviceId() + ",流水号:" + boxResponse.getData().getTransacSeq(),
							JSON.toJSONString(boxResponse)));

					if (boxCallBack != null) {
						try {
							boxCallBack.callback(boxResponse);
						} catch (Exception e) {
							logger.error(LogUtils.build(boxResponse.getMessgeType(), "接收app返回通讯盒消息回调", "回调失败",
									JSON.toJSONString(boxResponse)), e);
						}
					}
					
					SecurityService securityService = (SecurityService) ApplicationContextUtils.getApplicationContext().getBean("securityService");
					// 明文域加密
					boxResponse = securityService.plainTextEncrypt(boxResponse);

					// 添加MAC
					boxResponse.setKey(securityService.getSecurityMac(boxResponse));
					
					if (boxResponse.getKey() == null) {
						boxResponse.setKey("");
					}
					
					logger.info(LogUtils.build(messageType, "同步返回数据",
							"通讯盒:" + boxRequest.getData().getDeviceId() + ",流水号:" + boxRequest.getData().getTransacSeq(),
							JSON.toJSONString(boxResponse)));
					
					ByteBuf byteBuf = Unpooled
							.wrappedBuffer(JSON.toJSONString(boxResponse).getBytes(BoxConstants.CHARSET_UTF8));
					channelHandlerContext.writeAndFlush(byteBuf);
				}
			}
		} catch (Exception e) {
			// TODO 异常处理
			logger.error("调用app服务失败," + e.getMessage(), e);
		}
	}
}